home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
NOVA - For the NeXT Workstation
/
NOVA - For the NeXT Workstation.iso
/
SourceCode
/
Calendar
/
Calendar.m
< prev
next >
Wrap
Text File
|
1992-12-19
|
13KB
|
537 lines
//----------------------------------------------------------------------------------------------------
//
// Calendar
//
// Inherits From: Control
//
// Declared In: Calendar.h
//
// Disclaimer
//
// You may freely copy, distribute and reuse this software and its
// associated documentation. I disclaim any warranty of any kind,
// expressed or implied, as to its fitness for any particular use.
//
//----------------------------------------------------------------------------------------------------
#import "Calendar.h"
static const char* DAYS [7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
static const char* MONTHS [12] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
static int LAST_DAY_OF_MONTH [13] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
char dateString [25];
@implementation Calendar
//----------------------------------------------------------------------------------------------------
// Private Methods
//----------------------------------------------------------------------------------------------------
- _initMonthTextField
{
// Create the monthTextField instance and add it as a subview.
Font* font = [Font newFont:"Helvetica-Bold" size:12 style:0 matrix:NX_FLIPPEDMATRIX];
NXRect frameRect = {5.0, 114.0, 94.0, 15.0};
monthTextField = [[TextField allocFromZone:[self zone]] initFrame: &frameRect];
[monthTextField setEditable: NO];
[monthTextField setBezeled: NO];
[monthTextField setBackgroundColor: NX_COLORLTGRAY];
[monthTextField setFont: font];
[self addSubview: monthTextField];
return self;
}
- _initYearTextField
{
// Create the yearTextField instance and add it as a subview.
Font* font = [Font newFont:"Helvetica-Bold" size:12 style:0 matrix:NX_FLIPPEDMATRIX];
NXRect frameRect = {133.0, 114.0, 33.0, 15.0};
yearTextField = [[TextField allocFromZone:[self zone]] initFrame: &frameRect];
[yearTextField setEditable: NO];
[yearTextField setBezeled: NO];
[yearTextField setAlignment: NX_RIGHTALIGNED];
[yearTextField setBackgroundColor: NX_COLORLTGRAY];
[yearTextField setFont: font];
[self addSubview: yearTextField];
return self;
}
- _initWeekdayTextField
{
// Create the weekdayTextField instance and add it as a subview.
Font* font = [Font newFont:"Helvetica-Bold" size:10 style:0 matrix:NX_FLIPPEDMATRIX];
NXRect frameRect = {7.0, 96.0, 157.0, 13.0};
weekdayTextField = [[TextField allocFromZone:[self zone]] initFrame: &frameRect];
[weekdayTextField setEditable: NO];
[weekdayTextField setBezeled: NO];
[weekdayTextField setAlignment: NX_CENTERED];
[weekdayTextField setBackgroundColor: NX_COLORDKGRAY];
[weekdayTextField setTextColor: NX_COLORWHITE];
[weekdayTextField setFont: font];
[weekdayTextField setStringValue: " S M T W T F S"];
[self addSubview: weekdayTextField];
return self;
}
- _initDayMatrix
{
// Create the dayMatrix ButtonCell Matrix and add it as a subview.
id buttonCell;
int cellTag = 0;
int row;
int column;
Font* font = [Font newFont:"Helvetica" size:10 style:0 matrix:NX_FLIPPEDMATRIX];
NXRect matrixRect = {7.0, 3.0, 161.0, 90.0};
NXRect cellRect = {0.0, 0.0, 23.0, 15.0};
NXSize cellSize = {0.0, 0.0};
buttonCell = [[ButtonCell allocFromZone:[self zone]] initTextCell: ""];
[buttonCell setHighlightsBy: NX_CHANGEGRAY];
[buttonCell setType: NX_ONOFF];
[buttonCell setEditable: NO];
[buttonCell setBordered: NO];
[buttonCell setFont: font];
dayMatrix = [[Matrix allocFromZone:[self zone]] initFrame:&matrixRect mode:NX_RADIOMODE prototype:buttonCell numRows:6 numCols:7];
for (row = 0; row < 6; row++)
for (column = 0; column < 7; column++)
[[dayMatrix cellAt:row :column] setTag: cellTag++];
[dayMatrix setIntercell:&cellSize];
[dayMatrix setCellSize:&cellRect.size];
[dayMatrix sizeToCells];
[dayMatrix setAutodisplay:YES];
[[dayMatrix setTarget: self] setAction: @selector (_daySelected:)];
[dayMatrix setEmptySelectionEnabled: YES];
[self addSubview: dayMatrix];
return self;
}
- _initWithSystemDate
{
struct timeval greenwich;
struct tm* today;
gettimeofday (&greenwich, NULL);
today = (localtime (&(greenwich.tv_sec)));
day = today->tm_mday;
month = 1 + today->tm_mon;
year = 1900 + today->tm_year;
return self;
}
- (int) _lastDayOfMonth
{
if (month == 0) [self _initWithSystemDate];
if (month == 2) LAST_DAY_OF_MONTH[1] = (year % 4 ? 28 : 29);
return LAST_DAY_OF_MONTH [month - 1];
}
- (int) _firstWeekdayOfMonth
{
int theMonth = month;
int theYear = year;
int weekDay;
int offset;
long julian;
if (theMonth <= 2) { theYear--; theMonth += 12; }
offset = 0;
if ((theYear * 10000.0) + (theMonth * 100.0) + 1 >= 15821015.0)
offset = (2 - (theYear / 100)) + ((theYear / 100) / 4);
julian = (365.25 * theYear);
julian += (long) (30.6001 * (theMonth +1));
julian += (long) 1;
julian += 1720994L;
julian += (long) offset;
weekDay = (int) ((julian + 2) % 7);
return (weekDay < 0 || weekDay > 6 ? 0 : weekDay);
}
- _highlightCurrentDay
{
// Called by _updateCalendar and day: methods to select current day.
int firstWeekday;
id selectedCell;
[dayMatrix selectCellAt: -1 :-1];
if (day == 0) return self;
firstWeekday = [self _firstWeekdayOfMonth];
selectedCell = [dayMatrix findCellWithTag: day + firstWeekday - 1];
if ([selectedCell title])
if (strcmp ([selectedCell title], ""))
[dayMatrix selectCellWithTag: day + firstWeekday - 1];
return self;
}
- _sendActionToTarget
{
if ([self target] && [self isEnabled])
if ([[self target] respondsTo: [self action]])
[[self target] perform:[self action] with:self];
return self;
}
- _daySelected: sender
{
// Private action method for dayMatrix. Send user's action to target.
day = ([sender selectedCell] ? atoi ([[sender selectedCell] title]) : 0);
[self _sendActionToTarget];
return self;
}
- _updateCalendar
{
// Handles display update of subviews.
int date;
int cellTag;
int firstWeekday = [self _firstWeekdayOfMonth];
int lastDayOfMonth = [self _lastDayOfMonth];
char dateString[3];
[[dayMatrix window] disableDisplay];
for (cellTag = 0; cellTag < firstWeekday; cellTag++)
[[[dayMatrix findCellWithTag: cellTag] setTitle: ""] setEnabled: NO];
for (cellTag = lastDayOfMonth; cellTag < [dayMatrix cellCount]; cellTag++)
[[[dayMatrix findCellWithTag: cellTag] setTitle: ""] setEnabled: NO];
for (cellTag = firstWeekday, date = 1; date <= lastDayOfMonth; cellTag++, date++)
{
sprintf (dateString, "%d", date);
[[[dayMatrix findCellWithTag: cellTag] setTitle: dateString] setEnabled: isEnabled];
}
[self _highlightCurrentDay];
[monthTextField setStringValue: MONTHS [month - 1]];
[yearTextField setIntValue: year];
[[dayMatrix window] reenableDisplay];
[self display];
return self;
}
- _nextText: sender
{
// Called by 'takeFrom' methods to assist UI flow.
if ([sender isKindOf: [TextField class]])
if ([[sender nextText] respondsTo: @selector(selectText:)])
[[sender nextText] selectText:nil];
return self;
}
//----------------------------------------------------------------------------------------------------
// Initializing and Freeing
//----------------------------------------------------------------------------------------------------
- initFrame: (const NXRect*) frameRect
{
// Init and display current date. Create an ActionCell instance to
// hold our target/action values. Enable day selection.
[super initFrame: frameRect];
[self setCell: [[ActionCell allocFromZone:[self zone]] init]];
[self setEnabled: YES];
[self _initMonthTextField];
[self _initYearTextField];
[self _initWeekdayTextField];
[self _initDayMatrix];
[self _initWithSystemDate];
[self _updateCalendar];
return self;
}
- free
{
if (dayMatrix) [dayMatrix free];
if (monthTextField) [monthTextField free];
if (yearTextField) [yearTextField free];
if (weekdayTextField) [weekdayTextField free];
return [super free];
}
//----------------------------------------------------------------------------------------------------
// Accessors
//----------------------------------------------------------------------------------------------------
- month: (int) aMonth
{
month = (aMonth < 1 || aMonth > 12 ? 1 : aMonth);
[self _updateCalendar];
return self;
}
- day: (int) aDay
{
day = (aDay < 1 || aDay > [self _lastDayOfMonth] ? 0 : aDay);
[self _highlightCurrentDay];
return self;
}
- year: (int) aYear
{
year = (aYear < 1 || aYear > 9999 ? 1 : aYear);
[self _updateCalendar];
return self;
}
- (const char*) monthStringValue
{
return [monthTextField stringValue];
}
- (const char*) dayStringValue
{
return ([[dayMatrix selectedCell] title]);
}
- (const char*) yearStringValue
{
return [yearTextField stringValue];
}
- (const char*) dayOfWeekStringValue
{
return DAYS [([[dayMatrix selectedCell] tag] % 7)];
}
- (const char*) dateStringValue
{
if (day)
sprintf (dateString, "%s %d, %.4d", [self monthStringValue], day, [self yearIntValue]);
else
sprintf (dateString, "%s %.4d", [self monthStringValue], [self yearIntValue]);
return dateString;
}
- (int) monthIntValue
{
return month;
}
- (int) dayIntValue
{
return day;
}
- (int) yearIntValue
{
return year;
}
- (int) dayOfWeekIntValue
{
return ([[dayMatrix selectedCell] tag] % 7);
}
- (const char*) stringValue
{
return [self dateStringValue];
}
- (int) intValue
{
return day;
}
- (float) floatValue
{
return (float) day;
}
- (double) doubleValue
{
return (double) day;
}
//----------------------------------------------------------------------------------------------------
// Enabling Day Selection
//----------------------------------------------------------------------------------------------------
- setEnabled: (BOOL) aFlag
{
// Set enabling of day selection to aFlag and redisplay calendar (this will
// force update of dayMatrix buttonCells which are what actually gets
// enabled or disabled). Since the subview dayMatrix handles the mouse
// events we're interested in, we (the superview) will always remain disabled.
isEnabled = aFlag;
[self _updateCalendar];
[super setEnabled: NO];
return self;
}
- (BOOL) isEnabled
{
return isEnabled;
}
//----------------------------------------------------------------------------------------------------
// Action Methods
//----------------------------------------------------------------------------------------------------
- incrementMonth: sender
{
if (++month > 12) month = 1;
[self _updateCalendar];
return self;
}
- decrementMonth: sender
{
if (--month < 1) month = 12;
[self _updateCalendar];
return self;
}
- incrementYear: sender
{
if (++year > 9999) year = 1;
[self _updateCalendar];
return self;
}
- decrementYear: sender
{
if (--year < 1) year = 9999;
[self _updateCalendar];
return self;
}
- takeMonthIntValueFrom: sender
{
if ([sender isKindOf: [Matrix class]]) sender = [sender selectedCell];
if ([sender respondsTo: @selector (intValue)]) [self month: [sender intValue]];
[self _nextText: sender];
return self;
}
- takeDayIntValueFrom: sender
{
if ([sender isKindOf: [Matrix class]]) sender = [sender selectedCell];
if ([sender respondsTo: @selector (intValue)]) [self day: [sender intValue]];
[self _nextText: sender];
return self;
}
- takeYearIntValueFrom: sender
{
if ([sender isKindOf: [Matrix class]]) sender = [sender selectedCell];
if ([sender respondsTo: @selector (intValue)]) [self year: [sender intValue]];
[self _nextText: sender];
return self;
}
- showSystemDate: sender
{
[self _initWithSystemDate];
[self _updateCalendar];
return self;
}
//----------------------------------------------------------------------------------------------------
// Archiving
//----------------------------------------------------------------------------------------------------
- read: (NXTypedStream*) stream
{
[super read: stream];
NXReadTypes (stream, "iii@@@c",
&month, &day, &year, &monthTextField, &dayMatrix, &yearTextField, &isEnabled);
return self;
}
- write: (NXTypedStream*) stream
{
[super write: stream];
NXWriteTypes (stream, "iii@@@c",
&month, &day, &year, &monthTextField, &dayMatrix, &yearTextField, &isEnabled);
return self;
}
//----------------------------------------------------------------------------------------------------
// IB Methods
//----------------------------------------------------------------------------------------------------
- (const char*) getInspectorClassName
{
// Returns the name of the class responsible for managing custom
// IB Attributes inspection.
return "CalendarInspector";
}
- getMinSize:(NXSize *)minSize maxSize:(NXSize *)maxSize from:(int)where
{
// Constrains resize within IB.
minSize->width = maxSize->width = 175.0;
minSize->height = maxSize->height = 137.0;
return self;
}
@end